﻿using OAS.Application.System.Dtos;
using OAS.Application.WorkApp.Dtos;
using OAS.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace OAS.Application.WorkApp.Services
{
    public class WorkService : Repository<Work>, IWorkService, ITransient
    {
        public async Task<List<Work>> GetAllWork()
        {
            return await base.GetListAsync();
        }
        public async Task<List<DtoWork>> GetWorkByStatus()
        {
            Expression<Func<Work, User, bool>> sqlWhere = Expressionable.Create<Work, User>()
              .AndIF(UserContext.CurrentUser.RoleName == "主管", (o, user) => user.Department_Id == UserContext.CurrentUser.Department_Id)
              .AndIF(UserContext.CurrentUser.RoleName == "员工", (o, user) => (user.Department_Id == UserContext.CurrentUser.Department_Id && (o.Status == 0 || o.Status == 3)) || user.UserName == UserContext.CurrentUser.UserName)
              .ToExpression();
            var works = await base.AsQueryable().LeftJoin<User>((o, user) => o.Processor == user.UserName || o.Creator == user.UserName).Where(sqlWhere).ToListAsync();
            List<DtoWork> dtos = new();
            for (int status = 0; status < 4; status++)
            {
                DtoWork dto = new();
                dto.Status = status;
                dto.Children = works.DistinctBy(o=>o.Id).Where(o => o.Status == status)
                    .OrderByDescending(o => {
                        switch (o.Status)
                        {
                            case 1:
                                return o.ProcessTime;
                            case 2:
                                return o.FinishTime;
                            default:
                                return o.CreateTime;
                        }
                    }).Take(20).ToList();
                dtos.Add(dto);
            }
            return dtos;
        }
        public async Task<object> GetWorkList(DtoQuery dto)
        {
            Expression<Func<Work, User, bool>> sqlWhere = Expressionable.Create<Work, User>()
              .And((o, user) => o.Status == dto.Status)
              .AndIF(!string.IsNullOrEmpty(dto.KeyWord), (o, user) => o.TaskMsg.Contains(dto.KeyWord))
              .AndIF(UserContext.CurrentUser.RoleName == "主管", (o, user) => user.Department_Id == UserContext.CurrentUser.Department_Id)
              .AndIF(UserContext.CurrentUser.RoleName == "员工", (o, user) => (user.Department_Id == UserContext.CurrentUser.Department_Id && (o.Status == 0 || o.Status == 3)) || user.UserName == UserContext.CurrentUser.UserName)
              .ToExpression();
            var list = await base.AsQueryable()
                .LeftJoin<User>((o, user) => o.Processor == user.UserName || o.Creator == user.UserName)
                .Where(sqlWhere).ToListAsync();
            int total = list.DistinctBy(o => o.Id).Count();
            list = list.DistinctBy(o => o.Id).OrderByDescending(o => {
                switch (o.Status)
                {
                    case 1:
                        return o.ProcessTime;
                    case 2:
                        return o.FinishTime;
                    default:
                        return o.CreateTime;
                }
            }).Skip((dto.PageIndex - 1) * dto.PageSize).Take(dto.PageSize).ToList();
            return new { list, total };
        }
        public async Task AddWork(Work work)
        {
            work.Creator = UserContext.CurrentUser.UserName;
            work.CreateTime = DateTime.Now;
            await base.InsertAsync(work);
        }
        public async Task<Work> UpdateWork(Work work)
        {
            if(work.Status == 1)
            {
                work.Processor = UserContext.CurrentUser.UserName;
                work.ProcessTime = DateTime.Now;
            }
            else if(work.Status == 2)
            {
                work.Processor = UserContext.CurrentUser.UserName;
                work.FinishTime = DateTime.Now;
            }
            await base.UpdateAsync(work);
            return work;
        }
        public async Task DeleteWork(string[] ids)
        {
            await base.DeleteByIdsAsync(ids);
        }
    }
}
